package JoReg

import "fmt"

type Stmt struct {
	lexerPtr     *Lexer
	assignPtr    *Assign
	nameStackPtr *Stack
}

func MakeStmt(express string) *Stmt {
	stmtPtr := &Stmt{}
	lexerPtr := MakeLexer()
	lexerPtr.ParseToken(express)
	stmtPtr.lexerPtr = lexerPtr
	assignPtr := MakeAssign()
	stmtPtr.assignPtr = assignPtr
	stmtPtr.nameStackPtr = MakeStack()
	return stmtPtr
}

func (this *Stmt) parseStmt() {
	varName := this.assignPtr.getName()
	this.nameStackPtr.Push(varName)
	this.parseExpr()
	this.assignPtr.freeName()
	this.nameStackPtr.Pop()
	if this.lexerPtr.matchToken(SEMI) {
		this.lexerPtr.advance()
	} else {
		fmt.Printf("Missing Token Is Not Semi\n")
	}
}

func (this *Stmt) parseExpr() {
	this.parseTerm()
	this.parseExprPrime()
}

func (this *Stmt) parseTerm() {
	this.parseFactor()
	this.parseTermPrime()
}

// expr'
func (this *Stmt) parseExprPrime() {
	if this.lexerPtr.matchToken(PLUS) {
		this.lexerPtr.advance()
		varName := this.assignPtr.getName()
		upName := this.nameStackPtr.Top()
		this.nameStackPtr.Push(varName)
		this.parseTerm()
		fmt.Printf("%s+=%s\n", upName, varName)
		this.assignPtr.freeName()
		this.nameStackPtr.Pop()
		this.parseExprPrime()
	} else {
		fmt.Printf("Token is not Plus , current token is %c \n", this.lexerPtr.curToken().lexeme)
	}
}

// term'
func (this *Stmt) parseTermPrime() {
	if this.lexerPtr.matchToken(ASTERISK) {
		this.lexerPtr.advance()
		varName := this.assignPtr.getName()
		upName := this.nameStackPtr.Top()
		this.nameStackPtr.Push(varName)
		this.parseFactor()
		fmt.Printf("%s *= %s\n", upName, varName)
		this.assignPtr.freeName()
		this.nameStackPtr.Pop()
		this.parseTermPrime()
	} else {
		fmt.Printf("Token is not asterisk current token is %c \n", this.lexerPtr.curToken().lexeme)
	}
}

func (this *Stmt) parseAsterisk() {

}

func (this *Stmt) parsePlus() {
	if !this.lexerPtr.matchToken(PLUS) {
		fmt.Printf("parsePlus %c Error\n", this.lexerPtr.curToken().lexeme)
	}
	this.lexerPtr.advance()
}

func (this *Stmt) parseFactor() {
	if this.lexerPtr.matchToken(NUMBER) {
		varName := this.nameStackPtr.Top()
		fmt.Printf("%s = %c\n", varName, this.lexerPtr.curToken().lexeme)
		this.lexerPtr.advance()
	} else if this.lexerPtr.matchToken(OPEN_PAREN) {
		this.lexerPtr.advance()
		this.parseExpr()
		if this.lexerPtr.matchToken(CLOSE_PAREN) {
			this.lexerPtr.advance()
		} else {
			fmt.Printf("parse Error => lack close paren")
		}
	}
}

func (this *Stmt) parseOpenParent() {
}

func (this *Stmt) parseCloseParent() {

}

func isNumber(char byte) bool {
	if char >= 48 && char <= 57 {
		return true
	} else {
		return false
	}
}
